Ext.define('CA.base.Grid', {
    extend: 'Ext.grid.Panel',
    xtype: 'CA.base.Grid',

    controller: null,
    modelType: null,
    modelFields: null,
    modelIdProperty: null,
    extraParams: null,

    cls: 'c-no-dirty',

    initComponent: function(){
        var columns = this.columns || this.buildColumns(),
            tbar = this.tbar || [];

        if(this.editHandler){
            columns.push(this.editColumn());
        }

        if(this.removable){
            columns.push(this.removeColumn());
        }

        this.editing = Ext.create('Ext.grid.plugin.RowEditing');

        var config = {
            multiSelect: true,
            store: this.buildStore(),
            plugins: [this.editing],
            tbar: tbar.concat(this.buildToolbar()),
            columns: {
                defaults: {
                    hideable: false
                },
                items: columns
            },
            verticalScrollerType: 'paginggridscroller',
            loadMask: true,
            invalidateScrollerOnRefresh: false
        };

        Ext.apply(this, config);

        this.on('afterrender', this.onAfterRender, this);
        this.on('selectionchange', this.onSelectionChange, this);

        this.callParent();
    },

    buildToolbar: function(){
        var bar = [];

        if(this.removable){
            bar.push({
                text: 'Удалить',
                iconCls: 'c-icon-cancel',
                itemId: 'btnRemove',
                disabled: true,
                scope: this,
                handler: function(){
                    this.doRemoveRecord(this.getSelectionModel().selected.items);
                }
            });
        }

        if(this.hasSearch){

            bar.push('->');

            bar.push({
                width: 200,
                fieldLabel: 'Поиск',
                labelWidth: 50,
                store: this.store,
                xtype: 'searchfield'
            });
        }

        if(this.hasReload){
            this.hasSearch ? bar.push('-') : bar.push('->');

            bar.push({
                text: 'Обновить',
                iconCls: 'c-icon-reload',
                handler: this.reload,
                scope: this
            });
        }

        return bar;
    },

    onSelectionChange: function(sm, recs){
        var btnRemove = this.down('#btnRemove');

        if(btnRemove){
            btnRemove.setDisabled(!recs.length);
        }
    },

    onAfterRender: function(){
        this.getStore().guaranteeRange(0, 199);
    },

    editColumn: function(){
        return {
            xtype:'actioncolumn',
            width: 24,
            sortable: false,
            resizable: false,
            items: [{
                icon: CA.content('icons/16/edit.png'),
                tooltip: 'Редактировать',
                scope: this,
                handler: this.editHandler
            }]
        };
    },

    removeColumn: function(){
        return {
            xtype:'actioncolumn',
            width: 24,
            sortable: false,
            resizable: false,
            items: [{
                icon: CA.content('icons/16/cancel.png'),
                tooltip: 'Удалить',
                scope: this,
                handler: function(grid, rowIndex, colIndex) {
                    var store = this.getStore(),
                        rec = store.getAt(rowIndex);

                    this.doRemoveRecord(rec);
                }
            }]
        };
    },

    doRemoveRecord: function(recs){
        Ext.Msg.show({
            title: 'Подтверждение',
            msg: 'Продолжить удаление?',
            buttons: Ext.MessageBox.OKCANCEL,
            icon: Ext.MessageBox.WARNING,
            fn: function (btn) {
                if (btn == 'ok') {
                    this.removeRecord(recs);
                }
            },
            scope: this
        });
    },

    buildStore: function(){
        this.store = Ext.create('Ext.data.Store', {
            pageSize: 200,
            model: this.modelType,
            fields: this.modelFields,
            remoteSort: true,
            buffered: true,
            proxy: {
                type: 'jsonp',
                url: CA.url(this.controller + '/load'),
                extraParams: this.extraParams,
                reader: {
                    root: 'data',
                    totalProperty: 'total',
                    idProperty: this.modelIdProperty
                },
                simpleSortMode: true
            },
            sorters: this.sorters,
            listeners: {
                scope: this,
                update: this.onStoreUpdate
            }
        });

        return this.store;
    },

    removeRecord: function(recs){
        if(!Ext.isArray(recs)){
            recs = [recs];
        }

        var action = window[this.controller].remove,
            ids = Ext.pluck(recs, 'internalId'),
            el = this.getEl(),
            callback = function(resp){
                el.unmask();
                this.reload();
            },
            args = [ids];

        el.mask('Удаление...');

        if(this.extraParams){
            Ext.Object.each(this.extraParams, function(k, v){
                args.push(v);
            });
        }

        args = args.concat([callback, this]);

        action.apply(this, args);
    },

    reload: function(){
        this.getStore().load();
        this.verticalScroller.scrollToTop();
    },

    createRecord: function(record){
        var action = window[this.controller].create,
            store = this.getStore(),
            el = this.getEl();

        el.mask('Загрузка...');

        action(record.data, function(resp){
            record.set(resp.data);
            record.internalId = resp.data[record.idProperty];

            store.insert(0, record);
            el.unmask();
        });
    },

    onStoreUpdate: function(store, r){
        var action = window[this.controller].update,
            data = {},
            k,
            el = this.getEl(),
            callback = function(resp){
                el.unmask();
            },
            args = [r.internalId, data];

        el.mask('Удаление...');

        for(k in r.modified){
            data[k] = r.data[k];
        }

        if(this.extraParams){
            Ext.Object.each(this.extraParams, function(k, v){
                args.push(v);
            });
        }

        args = args.concat([callback, this]);
        action.apply(this, args);
    }
});
